home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 22 code / PCI Driver Sample / NCR_DriverProject / Src / NCRChipManager.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-08  |  9.8 KB  |  268 lines  |  [TEXT/MPCC]

  1. /*                                    NCRChipManager.c                                */
  2. /*
  3.  * NCRChipManager.c
  4.  * Copyright © 1994 Apple Computer Inc. All rights reserved.
  5.  */
  6. /*    .___________________________________________________________________________________.
  7.       | These low-level routines access the NCR 53C825 chip registers. They are needed    |
  8.     | to configure the chip on startup and to manage scripts. This is not a very good    |
  9.     | example of production-device programming: much of this could be done by resetting    |
  10.     | the chip and running a script. However, by doing this directly, we can do all        |
  11.     | I/O immediately. We'll use the Expansion Manager interface, even though the        |
  12.     | memory interface would be more efficient.                                            |
  13.     |                                                                                    |
  14.     | Almost everything here is specific to the NCR chip. NCRChipPowerUp might be         |
  15.     | generally useful.                                                                    |
  16.     |                                                                                    |
  17.     | Not all of this has been tested.                                                    |
  18.     .___________________________________________________________________________________.
  19. */
  20.  
  21. #include "NCRDriverPrivate.h"
  22. /*
  23.  * Chip operations are performed by copying bytes from our table to the NCR chip.
  24.  * a register value of 0xFF terminates the operation.
  25.  */
  26.  
  27. struct NCRRegisterOp {
  28.     unsigned char            chipRegister;
  29.     unsigned char            value;
  30. };
  31. typedef struct NCRRegisterOp    NCRRegisterOp, *NCRRegisterOpPtr;
  32.  
  33. /*
  34.  * The chip initialization sequence is taken from the NCR 53C825 Family Programming
  35.  * Guide, revision 1.0, table 7-10.
  36.  * The registers and bits are defined in the NCR 53C825 Data Manual, revision 1.1.
  37.  * You will need to read this documentation to understand what is going on here.
  38.  */
  39. enum{
  40.     EOF_OP            = 0xFF
  41. };
  42.  
  43. /*
  44.  * Initialization - this is the minimum we can get away with. It is insufficient for
  45.  * a production system.
  46.  */
  47. const NCRRegisterOp            gChipInitialize[] = {
  48.     { ISTAT,    bit7 | bit6                },    /* Abort operation, reset NCR chip        */
  49.     { ISTAT,    0                        },    /* Clear reset condition                */
  50.     { SCNTL0,    bit7 | bit6                },    /* Full arbitration                        */
  51.                                             /* Disable parity checking                */
  52.                                             /* Do not assert ATN on parity error    */
  53.                                             /* Initiator mode (only)                */
  54.     { SCNTL1,     bit7                     },    /* Extra clock cycle of data setup        */
  55.                                             /* Clear bus reset condition            */
  56.     { SCNTL3,    1                        },    /* No synchronous support, no wide SCSI    */
  57.     { SCXFER,    0                        },    /* Synchronous transfer param's unused    */
  58.      { CTEST3,    0                        },    /* Do not use PROM access                */
  59.      { CTEST4,    0                        },    /* Enable data transfer burst mode        */
  60.                                              /* Disable high-impedence modes            */
  61.                                              /* No master data phase parity checking    */
  62.     { DMODE,    0                        },    /* Burst Length == 2                    */
  63.                                             /* Source I/O Memory disabled            */
  64.                                             /* Destination I/O Memory disabled        */
  65.                                             /* Enable Read Line disabled            */
  66.                                             /* Burst Op Code Fetch disabled            */
  67.                                             /* Manual start mode disabled            */
  68.     { DIEN,        bit6 | bit5 | bit4 | bit2 | bit0 },    /* All interrupts enabled        */
  69.     { DCNTL,    0                        },    /* Single-step mode disabled            */
  70.                                             /* Totem-pole interrupt disabled        */
  71.                                             /* Start DMA operation disabled            */
  72.                                             /* 53C700 compatibility disabled        */
  73.     { SIEN0,    bit3 | bit2             },    /* Enable SCSI Gross Error interrupt    */
  74.                                             /* Unexpected disconnect interrupt        */
  75.     { SIEN1,    bit2 | bit1                },    /* Select & general timeout interrupts    */
  76.     { STIME0,    0x0D                    },    /* Selection timeout @ 409.6 msec.        */
  77.     { STIME1,    0                        },    /* No general purpose timeout            */
  78.     { RESPID0,    0                        },    /* We do not respond to selection        */
  79.     { RESPID1,    0                        },    /*  or reselection                        */
  80.     { STEST1,    0                        },    /* Use internal PCI bus clock            */
  81.     { STEST2,    bit1                    },    /* Disable SCSI Differential Mode        */
  82.                                             /* Enable extended REQ/ACK timing - do    */
  83.                                             /* not set this bit during fast SCSI    */
  84.                                             /* operation. It is more reliable for    */
  85.                                             /* slower operations                    */
  86.     { STEST3,    bit7                    },    /* Enable TolerANT technology            */
  87.                                             /* Start SCSI clock                        */
  88.     { EOF_OP,    0                        }
  89. };
  90.  
  91. const NCRRegisterOp            gChipTerminate[] = {
  92.     { DIEN,        0                        },    /* Disable all interrupts                */
  93.     { SIEN0,    0                         },    /* Disable SCSI interrupts                */
  94.     { SIEN1,    0                        },    /* Disable all timeout interrupts        */
  95.     { ISTAT,    bit7 | bit6                },    /* Abort operation, reset NCR chip        */
  96.     { ISTAT,    0                        },    /* Clear chip reset condition            */
  97.     { CTEST4,    bit5                    },    /* Put data bus in high-impedence state    */
  98.     { STEST3,    bit5                    },    /* Halt SCSI clock                        */
  99.     { EOF_OP,    0                        }
  100. };
  101.  
  102. /*
  103.  * This command sequence is executed by KillIO - it stops the current script. This
  104.  * will interrupt the computer and, eventually, complete any pending I/O. Note that
  105.  * there is a fairly elaborate process you must follow after setting an abort, but
  106.  * that will be handled in the I/O completion routine.
  107.  */
  108. const NCRRegisterOp            gChipStopCurrentScript[] = {
  109.     { ISTAT,    bit7                    },    /* Abort operation                        */
  110.     { EOF_OP,    0                        }
  111. };
  112.  
  113. void                        NCRConfigureChip(
  114.         const NCRRegisterOp        *opPtr
  115.     );
  116.  
  117. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  118.  * NCRInitializeChip is called at initialization to check that we are actually connected
  119.  * to a device we understand. It enables I/O and Memory space access and reads a chip
  120.  * test register to verify that parameters were passed in correctly. This would also
  121.  * be a good place to add chip self-tests.
  122.  */
  123. OSErr
  124. NCRInitializeChip(void)
  125. {
  126.         OSErr                    status;
  127.         OSStatus                osStatus;
  128.         UInt8                    ctest3;
  129.         UInt16                    commandWord;
  130.         StringPtr                failureMsg;
  131.  
  132.         Trace(NCRInitializeChip);
  133.         failureMsg = NULL;
  134.         /*
  135.          * Before we do anything, we need to connect the PCI card to the great
  136.          * universe of PCI bus operation. We are disconnected at power-up to
  137.          * prevent run-away hardware from crashing the system. In a production
  138.          * system, you probably won't enable both memory space and I/O space.
  139.          */
  140.         status = ExpMgrConfigReadWord(
  141.                     &GLOBAL.deviceEntry,
  142.                     (LogicalAddress) cwCommand,
  143.                     &commandWord
  144.                 );
  145.         CheckStatus(status, "\pExpMgrConfigReadWord");
  146.         if (status != noErr)
  147.             failureMsg = "\pInitChip: can't read command word";
  148.         if (status == noErr) {
  149.             commandWord |= 
  150.                     ( cwCommandSERREnable            /* Enable parity error check    */
  151.                     | cwCommandEnableParityError    /* Enable parity error reports    */
  152.                     | cwCommandEnableBusMaster        /* Let chip become bus master    */
  153.                     | cwCommandEnableMemorySpace    /* Respond to base address 1    */
  154.                     | cwCommandEnableIOSpace        /* Respond to base address 0    */
  155.                     );
  156.             status = ExpMgrConfigWriteWord(
  157.                         &GLOBAL.deviceEntry,
  158.                         (LogicalAddress) cwCommand,
  159.                         commandWord
  160.                     );
  161.             CheckStatus(status, "\pExpMgrConfigWriteWord");
  162.             if (status != noErr)
  163.                 failureMsg = "\pInitChip: Can't write command word";
  164.         }
  165.         if (status == noErr) {
  166.             /*
  167.              * Test whether the pci card is accessable (without crashing). This
  168.              * sequence reads a chip test register and verifies that the chip
  169.              * revision level matches the expected value. In a production system,
  170.              * this might be extended by a more elaborate self-test.
  171.              */
  172.             osStatus = DeviceProbe(
  173.                         (void *) (((UInt32) GLOBAL.pciCardBaseAddress) + CTEST3),
  174.                         &ctest3,
  175.                         k8BitAccess
  176.                     );
  177.             CheckStatus(osStatus, "\pDeviceProbe CTEST3");
  178.             if (osStatus != noErr) {
  179.                 status = osStatus;
  180.                 failureMsg = "\pInitChip: DeviceProbe failed";
  181.             }
  182.         }
  183.         if (status == noErr) {
  184.             if ((ctest3 & (bit7 | bit6 | bit5 | bit4)) != kPCIChipRevision) {
  185.                 LogHex(ctest3, "\pWrong ctest3 value at init");
  186.                 status = paramErr;
  187.                 failureMsg = "\pInitChip: Wrong chip revision";
  188.             }
  189.         }
  190.         if (status != noErr)
  191.             PublishInitFailureMsg(status, failureMsg);
  192.         return (status);
  193. }
  194.  
  195. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  196.  * NCRBusBusyCheck returns TRUE if the bus is busy and the NCR chip thinks that it
  197.  * is connected. Note that this is called from application context, so there may
  198.  * be a race condition. Returns noErr if the busy is busy, scsiUnableToTerminate
  199.  * if the bus is not busy, or we are not connected.
  200.  */
  201. OSErr
  202. NCRBusBusyCheck(void)
  203. {
  204.         UInt8                    istat;
  205.         
  206.         istat = ReadByte(ISTAT);
  207.         LogHex(istat, "\pNCRBusBusyCheck istat");
  208.         return ((istat & bit3) != 0) ? noErr : scsiUnableToTerminate;
  209. }
  210.  
  211. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  212.  * NCRResetChip executes a variety of chip-specific configuration operations.
  213.  *
  214.  * Currently, we don't do anything that can cause an error, but this module would
  215.  * typically be extended to include various chip-specific, and error-prone, tests.
  216.  */
  217. OSErr
  218. NCRResetChip(
  219.         NCRChipResetCommand        resetChipCommand
  220.     )
  221. {
  222.         OSErr                    status;
  223.         
  224.         Trace(NCRResetChip);
  225.         status = noErr;
  226.         switch (resetChipCommand) {
  227.         case kNCRResetChipInitialize:        /* Called on driver initialize            */
  228.             NCRConfigureChip(gChipInitialize);
  229.             /*
  230.              * The initiator ID is stored in the System Registry - this lets
  231.              * the user define the initiator ID at restart, which is needed if
  232.              * we intend to use the driver in a processor-processor configuration.
  233.              * Note that we disable reselection.
  234.              */
  235.             WriteByte(SCID, GLOBAL.initiatorID);
  236.             break;
  237.         case kNCRResetChipTerminate:        /* Called on driver termination            */
  238.             NCRConfigureChip(&gChipTerminate[0]);
  239.             break;
  240.         case kNCRResetChipPowerDown:        /* Handle PBControl driverPowerLow        */
  241.             NCRConfigureChip(&gChipTerminate[0]);
  242.             break;
  243.         case kNCRResetChipPowerUp:            /* Handle PBControl driverPowerHigh        */
  244.             NCRConfigureChip(&gChipInitialize[0]);
  245.             break;
  246.         case kNCRStopCurrentScript:
  247.             LogString("\pStopCurrentScript");
  248.             NCRConfigureChip(gChipStopCurrentScript);
  249.             LogString("\pAfter StopCurrentScript");
  250.             break;
  251.         }
  252.         return (status);
  253. }
  254.  
  255. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  256.  * NCRConfigureChip writes a stream of bytes to NCR chip registers.
  257.  */
  258. void
  259. NCRConfigureChip(
  260.         const NCRRegisterOp        *opPtr
  261.     )
  262. {
  263.         Trace(NCRConfigureChip);
  264.         for (; opPtr->chipRegister != EOF_OP; opPtr++)
  265.             WriteByte((opPtr->chipRegister & 0x000000FFL), opPtr->value);
  266. }
  267.  
  268.